home *** CD-ROM | disk | FTP | other *** search
/ Compendium Deluxe 2 / LSD and 17bit Compendium Deluxe - Volume II.iso / a / prog / cprog / illum.lha / clr_clip.c next >
Encoding:
C/C++ Source or Header  |  1988-04-18  |  5.5 KB  |  166 lines

  1. /* ****************************************************************
  2.  *                           clr_clip.c
  3.  * ****************************************************************
  4.  *  MODULE PURPOSE:
  5.  *      This module contains routines for bringing colors outside
  6.  *      the displayable gamut into the displayable gamut.
  7.  *
  8.  *  MODULE CONTENTS:
  9.  *      CLR_clamp_rgb   - clamps rgb values to 0.0-1.0 range
  10.  *      CLR_scale_rgb   - scales rgb values to 0.0-1.0 range
  11.  *      CLR_clip_rgb    - clips rgb values to 0.0-1.0 range
  12.  */
  13. #include <stdio.h>
  14. #include <math.h>
  15. #include "clr.h"
  16.  
  17. /* define the max and min scaling values for equal intensity
  18.  *  clipping.  These are defined to be slightly inside of the
  19.  *  0 to 1 range to avoid numerical problems that occur when
  20.  *  colors are on or very close to the clipping boundary.
  21.  */
  22. #define MAX_CLIP    0.9999  /* 1 - MAX_CLIP > 1 res step */
  23. #define MIN_CLIP    0.0001  /* less than 1 res step */
  24.  
  25. /* ****************************************************************
  26.  * CLR_clamp_rgb (rgb)
  27.  *  CLR_RGB     rgb     (in)  - the input rgb
  28.  *
  29.  * Returns clamped color.  Values greater than 1 are  clamped to 1,
  30.  *  values less than 0 are clamped to 0.
  31.  */
  32. CLR_RGB CLR_clamp_rgb(in_rgb)
  33. CLR_RGB     in_rgb;
  34. {   CLR_RGB     rgb;
  35.     rgb = in_rgb;
  36.     if (rgb.r < 0.0) rgb.r = 0.0;
  37.     else if (rgb.r > 1.0) rgb.r = 1.0;
  38.     if (rgb.g < 0.0) rgb.g = 0.0;
  39.     else if (rgb.g > 1.0) rgb.g = 1.0;
  40.     if (rgb.b < 0.0) rgb.b = 0.0;
  41.     else if (rgb.b > 1.0) rgb.b = 1.0;
  42.     return rgb;
  43. }
  44.  
  45. /* ****************************************************************
  46.  * CLR_scale_rgb (rgb)
  47.  *  CLR_RGB     rgb     (in)  - the input rgb
  48.  *
  49.  * Returns scaled color.  Values less than 0 are clamped to zero.
  50.  *  If any values are greater than 1, all color components are
  51.  *  scaled so the offending value is equal to 1.
  52.  */
  53. CLR_RGB CLR_scale_rgb(in_rgb)
  54. CLR_RGB     in_rgb;
  55. {   double      scale=1.0;
  56.     double      tmp_scale;
  57.     CLR_RGB     rgb;
  58.     rgb = in_rgb;
  59.     if (rgb.r < 0.0) rgb.r = 0.0;
  60.     else if ((rgb.r > 1.0) && ((tmp_scale = (1.0 / rgb.r))
  61.     < scale)) scale = tmp_scale;
  62.     if (rgb.g < 0.0) rgb.g = 0.0;
  63.     else if ((rgb.g > 1.0) && ((tmp_scale = (1.0 / rgb.g))
  64.     < scale)) scale = tmp_scale;
  65.     if (rgb.b < 0.0) rgb.b = 0.0;
  66.     else if ((rgb.b > 1.0) && ((tmp_scale = (1.0 / rgb.b))
  67.     < scale)) scale = tmp_scale;
  68.     if (scale < 1.0) {
  69.     rgb.r *= scale;
  70.     rgb.g *= scale;
  71.     rgb.b *= scale;
  72.     }
  73.     return rgb;
  74. }
  75.  
  76. /* ****************************************************************
  77.  * CLR_RGB CLR_clip_rgb(in_rgb)
  78.  *  CLR_RGB     in_rgb  (in) - the input rgb
  79.  *
  80.  * Returns the clipped color - clipping is by desaturating the
  81.  *  color by shifting it towards the neutral axis in a plane
  82.  *  perpendicular to the neutral axis.  The neutral axis is taken
  83.  *  as the vector from the monitor black to the monitor white.
  84.  */
  85. CLR_RGB CLR_clip_rgb(in_rgb)
  86. CLR_RGB     in_rgb;
  87. {   CLR_RGB     diff, out_rgb;
  88.     double      axis_rgb, diff_mult, tmp_mult;
  89.  
  90.     /* check to see if clipping is required
  91.      */
  92.     if ((in_rgb.r < 0.0) || (in_rgb.r > 1.0) ||
  93.     (in_rgb.g < 0.0) || (in_rgb.g > 1.0) ||
  94.     (in_rgb.b < 0.0) || (in_rgb.b > 1.0)) {
  95.     /* clipping is required, determine the distance from
  96.      *  the origin to the equal intensity plane containing
  97.      *  the color.  The distance is normalized the origin
  98.      *  at color (0,0,0) and a distance of 1 at (1,1,1)
  99.      */
  100.     axis_rgb = (in_rgb.r + in_rgb.g + in_rgb.b) * .333333;
  101.     /* check for the intensity plane of the color being
  102.      *  outside the displayable range -- if it is, set
  103.      *  color to either black or white.
  104.      */
  105.     if (axis_rgb <= MIN_CLIP)
  106.         /* this is not a visible color -- it should not
  107.          *  have been computed
  108.          */
  109.         out_rgb.r = out_rgb.g = out_rgb.b = 0.0;
  110.     else if (axis_rgb >= MAX_CLIP)
  111.         /* This is way beyond white in intensity, set it
  112.          *  to the white point.
  113.          */
  114.         out_rgb.r = out_rgb.g = out_rgb.b = 1.0;
  115.     else {
  116.         /* the intensity plane is within the displayable
  117.          *  range.  Compute the vector from the neutral
  118.          *  axis to the color on it's intensity plane.
  119.          *  The intersection of the neutral axis and the
  120.          *  intensity plane is at r=g=b=axis_rgb.
  121.          */
  122.         diff.r = in_rgb.r - axis_rgb;
  123.         diff.g = in_rgb.g - axis_rgb;
  124.         diff.b = in_rgb.b - axis_rgb;
  125.         /* determine the relative length of the vector
  126.          *  to the edge of the displayable color gamut.
  127.          */
  128.         diff_mult = 1.0;
  129.         if (in_rgb.r > 1.0) {
  130.         if ((tmp_mult = (MAX_CLIP - axis_rgb) / diff.r)
  131.             < diff_mult) diff_mult = tmp_mult;
  132.         } else if (in_rgb.r < 0.0) {
  133.         if ((tmp_mult = (MIN_CLIP - axis_rgb) / diff.r)
  134.             < diff_mult) diff_mult = tmp_mult;
  135.         }
  136.  
  137.         if (in_rgb.g > 1.0) {
  138.         if ((tmp_mult = (MAX_CLIP - axis_rgb) / diff.g)
  139.             < diff_mult) diff_mult = tmp_mult;
  140.         } else if (in_rgb.g < 0.0) {
  141.         if ((tmp_mult = (MIN_CLIP - axis_rgb) / diff.g)
  142.             < diff_mult) diff_mult = tmp_mult;
  143.         }
  144.  
  145.         if (in_rgb.b > 1.0) {
  146.         if ((tmp_mult = (MAX_CLIP - axis_rgb) / diff.b)
  147.             < diff_mult) diff_mult = tmp_mult;
  148.         } else if (in_rgb.b < 0.0) {
  149.         if ((tmp_mult = (MIN_CLIP - axis_rgb) / diff.b)
  150.             < diff_mult) diff_mult = tmp_mult;
  151.         }
  152.  
  153.         /* determine the location of the color at the
  154.          *  edge of the displayable color gamut.
  155.          */
  156.         out_rgb.r = axis_rgb + (diff.r * diff_mult);
  157.         out_rgb.g = axis_rgb + (diff.g * diff_mult);
  158.         out_rgb.b = axis_rgb + (diff.b * diff_mult);
  159.     }
  160.     return out_rgb;
  161.     }
  162.     else
  163.     return in_rgb;
  164. }
  165. /* ************************************************************* */
  166.